<template>
  <div
    v-show="visible"
    :style="{width: '70px', height: '70px', left: formatter(left), top: formatter(top), cursor: compassPosition.positionType === '5' ? 'move' : 'default'}"
    @mousedown="handleMouseDown"
    ref="self"
    class="compass"
  >
    <img
      class="full-box"
      src="../compass.svg"
    >
  </div>
</template>

<script>
import { debounce } from 'throttle-debounce'
import { mapState } from 'vuex'
export default {
  name: 'CompassContainer',
  props: {
    value: {
      type: Boolean,
      default: false
    },
    containerHeight: {
      type: Number,
      default: 0
    },
    containerWidth: {
      type: Number,
      default: 0
    }
  },
  data () {
    return {
      visible: this.value,
      left: 0,
      top: 0
    }
  },
  created () {
    this.debounceCommit = debounce(800, this.updateCompassPosition)
    this.$root.$on('updateMapMaking', this.updateMapMaking)
    this.$root.$on('updateCompass', this.updateCompass)
  },
  beforeDestroy () {
    this.$root.$off('updateMapMaking', this.updateMapMaking)
    this.$root.$off('updateCompass', this.updateCompass)
  },
  watch: {
    value (v) {
      this.visible = v
    },
    visible (v) {
      this.$emit('input', v)
      if (this.visible) {
        this.updateCompass()
      }
    },
    containerWidth (v, old) {
      this.oldWidth = old
      this.updateCompass()
    },
    containerHeight (v, old) {
      this.oldHeight = old
      this.updateCompass()
    }
  },
  computed: {
    ...mapState('map-making', ['compassPosition'])
  },
  methods: {
    updateMapMaking () {
      if (!isNaN(Number(this.compassPosition.left)) && !isNaN(Number(this.compassPosition.top))) {
        this.left = Number(this.compassPosition.left) * this.containerWidth
        this.top = Number(this.compassPosition.top) * this.containerHeight
      }
    },
    handleMouseDown (e) {
      if (this.compassPosition.positionType !== '5') return
      this.mouseX = e.x
      this.mouseY = e.y
      this.currentLeft = this.left
      this.currentTop = this.top
      this.dragging = true
      document.body.addEventListener('mousemove', this.handleMouseMove)
      document.body.addEventListener('mouseup', this.handleMouseUp)
    },
    handleMouseMove (e) {
      if (!this.dragging) return
      this.$refs.self.style.cursor = 'move'
      const left = this.currentLeft + (e.x - this.mouseX)
      const top = this.currentTop + (e.y - this.mouseY)
      this.left = Math.min(Math.max(0, left), this.containerWidth - this.$refs.self.offsetWidth)
      this.top = Math.min(Math.max(0, top), this.containerHeight - this.$refs.self.offsetHeight)
      this.debounceCommit()
    },
    handleMouseUp () {
      this.dragging = false
      document.body.removeEventListener('mousemove', this.handleMouseMove)
      document.body.removeEventListener('mouseup', this.handleMouseUp)
    },
    formatter (num) {
      return num + 'px'
    },
    updateCompassPosition () {
      this.$store.commit('map-making/setCompassPosition', Object.assign(this.compassPosition, { left: this.left / this.containerWidth, top: this.top / this.containerHeight }))
    },
    updatePosition () {
      if (this.oldWidth && this.oldHeight) {
        const leftRatio = this.left / this.oldWidth
        const topRatio = this.top / this.oldHeight
        this.left = Math.min(Math.max(0, leftRatio * this.containerWidth), this.containerWidth - this.$refs.self.offsetWidth)
        this.top = Math.min(Math.max(0, topRatio * this.containerHeight), this.containerHeight - this.$refs.self.offsetHeight)
        this.oldWidth = null
        this.oldHeight = null
        this.debounceCommit()
      }
    },
    async updateCompass () {
      await this.$nextTick()
      if (this.compassPosition.positionType === '5') {
        this.updatePosition()
      } else {
        if (this.compassPosition.positionType === '1') {
          this.left = 10
          this.top = 10
        } else if (this.compassPosition.positionType === '2') {
          this.left = 10
          this.top = this.containerHeight - this.$refs.self.offsetHeight - 10
        } else if (this.compassPosition.positionType === '3') {
          this.left = this.containerWidth - this.$refs.self.offsetWidth - 10
          this.top = 10
        } else if (this.compassPosition.positionType === '4') {
          this.left = this.containerWidth - this.$refs.self.offsetWidth - 10
          this.top = this.containerHeight - this.$refs.self.offsetHeight - 10
        }
        this.debounceCommit()
        this.oldWidth = null
        this.oldHeight = null
      }
    }
  }
}
</script>
<style lang="scss" scoped>
  .compass {
    position: absolute;
    user-select: none;
    z-index: 0;

    > img {
      pointer-events: none;
    }
  }
</style>
